type SSEHandlers = {
  onMessage?: (chunk: string) => void
  onError?: (e: Event | Error) => void
  onComplete?: () => void
}

// 标准 SSE 解析：按行处理，累积 data: 行，空行作为事件边界
// 同时兼容某些实现直接输出裸字符串（无 data: 与空行），此时直接透传增量 chunk
export function createSSE(url: string, handlers: SSEHandlers) {
  const controller = new AbortController()
  const signal = controller.signal

  fetch(url, { signal, headers: { Accept: 'text/event-stream' } })
    .then(async (res) => {
      if (!res.body) throw new Error('No response body for SSE')
      const reader = res.body.getReader()
      const decoder = new TextDecoder()

      let pendingLineBuffer = ''
      let eventDataBuffer = ''
      let sawDataPrefix = false

      while (true) {
        const { value, done } = await reader.read()
        if (done) break
        const text = decoder.decode(value, { stream: true })

        // 如果既没有\n\n分隔，也没有 data: 前缀，判定为裸流，直接透传
        if (!sawDataPrefix && !text.includes('\n') && !text.includes('\r')) {
          if (text.length > 0) handlers.onMessage?.(text)
          continue
        }

        pendingLineBuffer += text
        // 统一换行
        const lines = pendingLineBuffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n')
        pendingLineBuffer = lines.pop() ?? ''

        for (const line of lines) {
          if (line === '') {
            // 事件结束
            if (eventDataBuffer.length > 0) {
              handlers.onMessage?.(eventDataBuffer)
              eventDataBuffer = ''
            }
            continue
          }
          if (line.startsWith(':')) {
            // 注释/心跳
            continue
          }
          const idx = line.indexOf(':')
          const field = idx === -1 ? line : line.slice(0, idx)
          let value = idx === -1 ? '' : line.slice(idx + 1)
          if (value.startsWith(' ')) value = value.slice(1)
          if (field === 'data') {
            sawDataPrefix = true
            eventDataBuffer += value + '\n'
          }
        }
      }

      // flush 残留事件
      if (eventDataBuffer.length > 0) {
        // 去掉尾随换行
        if (eventDataBuffer.endsWith('\n')) eventDataBuffer = eventDataBuffer.slice(0, -1)
        handlers.onMessage?.(eventDataBuffer)
      } else if (pendingLineBuffer.trim().length > 0 && !sawDataPrefix) {
        // 裸流残留
        handlers.onMessage?.(pendingLineBuffer)
      }
      handlers.onComplete?.()
    })
    .catch((e) => {
      handlers.onError?.(e as Error)
      handlers.onComplete?.()
    })

  return {
    close: () => controller.abort()
  }
}

// 适配 SseEmitter + text/event-stream
export function createEventSourceSSE(url: string, onChunk: (chunk: string) => void, onDone: () => void) {
  const es = new EventSource(url)
  es.onmessage = (ev) => {
    onChunk(ev.data)
  }
  es.onerror = () => {
    es.close()
    onDone()
  }
  es.onopen = () => {
    // no-op
  }
  return es
}



